function varargout = TLAssignmentDlg(action,varargin)

% TL_ASSIGNMENT_DLG manages the user interface for TargetLink Assignment block
%
% SYNTAX dlgInfo = TLAssignmentDlg('GetDlgInfo');
%   gets dialog info of TargetLink Assignment block
%
%   INPUT ARGUMENTS
%   -/-      
%
%   OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%
% SYNTAX [sheetDims,ctrlPos] = ...
%           TLAssignmentDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLAssignmentDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLAssignmentDlg('Manage', pageName, dlgfig, dlgdata, pageActionUpd);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLAssignmentDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLAssignmentDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLAssignmentDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_SimBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.12 $
% $Date: 2011/03/17 11:50:41MEZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


switch action

    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'Assignment';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
        dlgInfo.pageNames   = {
            'Output'; ...
            'Autoscaling'; ...
            'Documentation'};
        varargout{1} = dlgInfo;
        varargout{2} = get_tlcg_data(hBlock);

    case 'CtrlPositions'
        pageName     = varargin{1};
        commonGeom   = varargin{2};
        sheetDims    = varargin{4};
        switch pageName
            case 'Output'
                [sheetDims, ctrlPos] = FcnCalcOutputCtrlPositions(commonGeom);

            case 'Autoscaling'
                excludedCtrls = {'logging', 'keepParameter'};
                [sheetDims, ctrlPos] = ...
                    TLManageLoggingCtrls('calcCtrls', commonGeom, sheetDims, excludedCtrls);

            case 'Documentation'
                bTblBlock = 0;
                bCodeComment = 1;
                [sheetDims, ctrlPos] = ...
                    TLManageDocCtrls('ctrlpos', commonGeom, sheetDims, ...
                    bCodeComment, bTblBlock);
        end
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;

    case 'Create'
        pageName = varargin{1};
        dlgfig   = varargin{2};
        dlgdata  = varargin{3};
        pageNum  = strmatch(pageName, dlgdata.pageNames, 'exact');
        switch pageName
            case 'Output'
                dlgdata = FcnCreateOutputPage(pageNum, dlgfig, dlgdata);
                
            case 'Autoscaling'
                dlgdata = TLManageLoggingCtrls('create',pageNum,dlgfig,dlgdata);
                
            case 'Documentation'
                dlgdata = TLManageDocCtrls('create',pageNum,dlgfig,dlgdata);
        end
        dlgdata.pageData{pageNum}.ctrlPos = [];
        varargout{1} = dlgdata;

    case 'Manage',
        pageName   = varargin{1};
        dlgfig     = varargin{2};
        dlgdata    = varargin{3};
        pageAction = varargin{4};
        pageNum    = strmatch(pageName,dlgdata.pageNames,'exact');

        switch pageName
            case 'Output'
                [dlgdata, bModified] = FcnManageOutputPage(pageNum, dlgfig, dlgdata, pageAction);
                
            case 'Autoscaling'
                [dlgdata, bModified] = ...
                    TLManageLoggingCtrls('manage', pageNum, dlgdata, pageAction, 'logdata');

            case 'Documentation'
                [dlgdata,bModified] = ...
                    TLManageDocCtrls('callback', pageNum, dlgfig, ...
                    dlgdata, pageAction);
        end
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'ManageSystemIcons',
        dlgfig     = varargin{1};
        dlgdata    = varargin{2};
        pageAction = varargin{3};
        [dlgdata, bModified] = FcnManageSystemIcons(dlgfig,dlgdata,pageAction);
        varargout{1} = dlgdata;
        varargout{2} = bModified;

    case 'Update'
        dlgfig  = varargin{1};
        dlgdata = varargin{2};
        pageNum = varargin{3};

        pageName  = dlgdata.pageNames{pageNum};
        switch pageName
            case 'Output'
                dlgdata = FcnUpdateOutputPage(dlgdata, dlgfig, pageNum);
                
            case 'Autoscaling'
                dlgdata =  TLManageLoggingCtrls('update',pageNum,dlgdata,'','output');
                TLManageLoggingCtrls('setCtrls',pageNum, dlgfig, dlgdata);
                
            case 'Documentation'
                TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
        end
        varargout = {dlgdata};

    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;

    otherwise
        error(['Invalid action "' action '"']);
end


%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manage actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        % look for associated production code file
        [codefile,blockstr] = get_codefile(dlgdata.model);
        if ~isempty(codefile)
            codeedit(codefile,blockstr);
        end

    case 'ViewCode'
        tl_create_links_to_model('ShowComputation',dlgdata.model, 'output');

    otherwise
        error('Invalid callback');

end % switch(action)


%-----------------------------------------------------------------------------------------
% FcnOutputCtrlPositions calculates positions for all controls on output page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCalcOutputCtrlPositions(commonGeom)

excludedCtrls = {'saturate'};
[sheetDims, ctrlPos, col, colDelta, rowDelta] = ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

% floating point options (initial condition and stepsize) controls
strings_and_styles = {...
    'Source of element indices:',       'text';
    'external    ',                     'popupmenu';
    'Elements',                         'text';
    'Omit dispensable initializations', 'checkbox';
    'Zero-based indexing',              'checkbox'};

[elementSourceLabelSize, ...
    elementSourcePopupSize, ...
    elementsLabelSize, ...
    omitInitsCheckboxSize, ...
    zeroIdxCheckboxSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

%-----------------------------------------------------------
% enlarge addoptGroupbox
%-----------------------------------------------------------

% define new height for addoptGroupbox
ctrlPos.addoptGroupbox(4) = commonGeom.editHeight ...
    + commonGeom.checkboxHeight ...
    + rowDelta ...
    + commonGeom.frameBottomEdgeBuffer ...
    + commonGeom.frameTopEdgeBuffer;

%---------------------------------------
% 2nd row
cy = commonGeom.frameBottomEdgeBuffer;

% zero-based indexing checkbox
cx = col(1);
ctrlPos.zeroIdxCheckbox = [cx cy zeroIdxCheckboxSize];

%---------------------------------------
% 1st row
cy = cy + commonGeom.checkboxHeight + rowDelta;

% source label
cx = col(1);
ctrlPos.elementSourceLabel = [cx cy elementSourceLabelSize];

% source edit field
cx = cx + elementSourceLabelSize(1) + colDelta / 3;
ctrlPos.elementSourcePopup = [cx cy elementSourcePopupSize];

% elements label
cx = cx + elementSourcePopupSize(1) + colDelta;
ctrlPos.elementsLabel = [cx cy elementsLabelSize];

% elements edit field
cx = cx + elementsLabelSize(1) + colDelta / 3;
ctrlPos.elementsEdit = [cx cy ctrlPos.lsbEdit(3:4)];

% omnit intialisations checkbox
cx = cx + ctrlPos.elementsEdit(3) + colDelta;
ctrlPos.omitInitsCheckbox = [cx cy omitInitsCheckboxSize];

% increase sheet dimensions
sheetDims(2) = sheetDims(2) ...
    + ctrlPos.addoptGroupbox(4) ...
    + commonGeom.textHeight;


%-----------------------------------------------------------------------------------------
% FcnCreateOutputPage creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateOutputPage(pageNum,dlgfig,dlgdata)

% create all controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
currentElement = 1;
dlgdata = TLManageScalingCtrls('create', pageNum, dlgfig, ...
    dlgdata, 'output', currentElement);

ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
Children = dlgdata.pageData{pageNum}.children;
pageName = dlgdata.pageNames{pageNum};

Children.addoptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Element indices'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.addoptGroupbox);

% element controls
Children.elementSourcePopup = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'Popupmenu', ...
    'BackgroundColor',    'w', ...
    'String',             {'internal'}, ...
    'Position',           ctrlPos.elementSourcePopup, ...
    'Callback',          sprintf('tldlg(''%s'',gcbf,''elementSourcePopup'')',pageName));

Children.elementSourceLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'Source of element indices:', ...
    'Position',           ctrlPos.elementSourceLabel);

Children.elementsLabel = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'text', ...
    'String',             'Elements:', ...
    'Position',           ctrlPos.elementsLabel);

Children.elementsEdit = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'edit', ...
    'Position',           ctrlPos.elementsEdit, ...
    'Callback',          sprintf('tldlg(''%s'',gcbf,''elementsEdit'')',pageName));

% omit initializations
Children.omitInitsCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Omit dispensable initializations', ...
    'Position',           ctrlPos.omitInitsCheckbox, ...
    'Callback',          sprintf('tldlg(''%s'',gcbf,''omitInitsCheckbox'')',pageName));

Children.zeroIdxCheckbox = uicontrol( ...
    'Parent',             Children.addoptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Zero-based indexing', ...
    'Position',           ctrlPos.zeroIdxCheckbox, ...
    'Callback',          sprintf('tldlg(''%s'',gcbf,''zeroIdxCheckbox'')',pageName));

dlgdata.pageData{pageNum}.children = Children;


%-----------------------------------------------------------------------------------------
% FcnManageOutputPage manages control actions of output page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageOutputPage(pageNum, dlgfig, dlgdata, action)

Children = dlgdata.pageData{pageNum}.children;

switch action
    case 'elementSourcePopup'
        dlgdata.data.elementsource = get(Children.elementSourcePopup, 'Value');
        bModified = 1;

    case 'elementsEdit'
        elements = get(Children.elementsEdit, 'String');
        if ~isempty(elements)
            dlgdata.data.elements = elements;
        else
            beep;
        end
        bModified = 1;

    case 'omitInitsCheckbox'
        dlgdata.data.omitinitializations = ...
            get(Children.omitInitsCheckbox, 'Value');
        bModified = 1;

    case 'zeroIdxCheckbox'
        dlgdata.data.zeroidx = get(Children.zeroIdxCheckbox, 'Value');
        bModified = 1;

    otherwise
        [dlgdata,bModified1] = TLManageVariableCtrls('manage', ...
            pageNum, dlgfig, dlgdata, action, 'output');

        [dlgdata,bModified2] = TLManageScalingCtrls('manage', ...
            pageNum, dlgfig, dlgdata, action, 'output');

        bModified = bModified1 | bModified2;
end


%--------------------------------------------------------------------------
% FcnUpdateOutputPage updates the controls of the output tab
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%   dlgfig      figure handle of dialog
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateOutputPage(dlgdata,dlgfig,pageNum)

Children = dlgdata.pageData{pageNum}.children;

% update all variable controls
dlgdata = TLManageVariableCtrls('update', pageNum, dlgdata, 'output');
constraint = [];
dlgdata = TLManageScalingCtrls('update', pageNum, dlgdata, 'output', constraint);

% default control status for controls
sources = {'internal', 'external'};
elementSourcePopupCtrlStatus = struct('enable', 'on', ...
    'string', {sources}, 'value', 1);
elementsEditCtrlStatus = struct('enable', 'on', 'string', '');
omitInitsCheckboxCtrlStatus = struct('enable', 'on', 'value', 0);
zeroIdxCheckboxCtrlStatus = struct('enable', 'on', 'value', '0');

elementSourcePopupCtrlStatus.value = dlgdata.data.elementsource;
elementsEditCtrlStatus.enable = flag2str(dlgdata.data.elementsource == 1);
elementsEditCtrlStatus.string = dlgdata.data.elements;
omitInitsCheckboxCtrlStatus.value = dlgdata.data.omitinitializations;
omitInitsCheckboxCtrlStatus.enable = flag2str(FcnIsBlockInsideLoop(dlgdata));
zeroIdxCheckboxCtrlStatus.value = dlgdata.data.zeroidx;

% write control status of extra controls to the control
ctrlsList = {
    'elementSourcePopup', ...
    'elementsEdit', ...
    'omitInitsCheckbox', ...
    'zeroIdxCheckbox'};
for ctrlsNo = 1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end

% set controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageScalingCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLSetCtrlsStatus(dlgfig, Children, ctrlsList);


%--------------------------------------------------------------------------
% FcnUpdateOutputPage determines whether this block is inside a loop, one of its parent
%   subsystems contains a While or For Iterator block.
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   bInsideLoop flag =1, if block is inside a loop, =0 otherwise
%--------------------------------------------------------------------------
function bInsideLoop = FcnIsBlockInsideLoop(dlgdata)

parent = get_param(dlgdata.model, 'Parent');
bInsideLoop = 0;
while strcmp(get_param(parent, 'Type'), 'block')
    if ~isempty(find_system(parent, ...
            'SearchDepth',    1, ...
            'LookUnderMasks', 'on', ...
            'FollowLinks',    'on', ...
            'BlockType',      'ForIterator')) ...
            || ~isempty(find_system(parent, ...
            'SearchDepth',    1, ...
            'LookUnderMasks', 'on', ...
            'FollowLinks',    'on', ...
            'BlockType',      'WhileIterator'))
        bInsideLoop = 1;
        break;
    elseif any(strcmp(get_param(parent, 'Tag'), ...
            {'MIL Subsystem', 'disabled MIL Subsystem'}))
        break;
    end
    parent = get_param(parent, 'Parent');
end
